#include <iostream>   // 用于标准输入输出
#include <vector>     // 用于动态数组 std::vector
#include <string>     // 用于字符串 std::string
#include <numeric>    // 用于 std::iota
#include <algorithm>  // 用于 std::next_permutation
#include <map>        // 用于 std::map

// 全局变量
int N_in;                // 输入的N，表格的维度
std::string S[10][10]; // 存储加法表，最大10x10，使用1-based索引方便对题

// 函数：将字符串 s_val 按照进制 b 和字符映射 mp 转换为整数值
long long parse(const std::string& s_val, const std::map<char, int>& mp, int b) {
    long long current_sum = 0;
    for (char c_digit : s_val) { // 从左到右遍历字符串中的每个字符
        // map::at(key) 会返回key对应的value，如果key不存在则抛出异常
        // 根据题意，参与运算的字符一定在映射表中
        current_sum = current_sum * b + mp.at(c_digit);
    }
    return current_sum;
}

int main() {
    // 使用较快的C++标准I/O（非必须，N较小）
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(NULL);

    std::cin >> N_in; // 读取N

    // 读取整个加法表
    for (int i = 1; i <= N_in; ++i) {
        for (int j = 1; j <= N_in; ++j) {
            std::cin >> S[i][j];
        }
    }

    int k = N_in - 1; // 实际参与运算的字符数量 (即数字的个数)
    int base = N_in - 1;  // 进制数

    std::vector<char> C(k); // 存储 k 个字符，按输入顺序
    // 字符列表在输入表格的 S[1][2], S[1][3], ..., S[1][N_in]
    for (int i = 0; i < k; ++i) {
        C[i] = S[1][i + 2][0]; // S[1][i+2]是一个字符串，取其第0个字符
    }

    std::vector<int> P(k); // 存储分配给字符的数值的排列
    // 初始化P为 {0, 1, ..., k-1}
    std::iota(P.begin(), P.end(), 0);

    // 尝试 P 的所有排列
    do {
        std::map<char, int> M; // 当前字符到数值的映射
        for (int i = 0; i < k; ++i) {
            M[C[i]] = P[i]; // C[i] 这个字符映射到 P[i] 这个值
        }

        bool ok = true; // 标记当前排列是否满足所有加法等式
        // 检查加法表中的 k*k 个加法运算
        // r_idx 和 c_idx 是原始表格中的行号和列号
        for (int r_idx = 2; r_idx <= N_in; ++r_idx) {
            for (int c_idx = 2; c_idx <= N_in; ++c_idx) {
                char char1 = S[r_idx][1][0]; // 第一个加数对应的字符
                char char2 = S[1][c_idx][0]; // 第二个加数对应的字符

                long long val1 = M.at(char1); // 第一个加数的数值
                long long val2 = M.at(char2); // 第二个加数的数值
                
                long long sum_expected = val1 + val2; // 期望的和
                // 从表格S[r_idx][c_idx]中读取字符串形式的和，并用当前映射和进制转换为数值
                long long sum_from_table = parse(S[r_idx][c_idx], M, base);

                if (sum_expected != sum_from_table) { // 如果计算结果与表中不符
                    ok = false; // 当前排列无效
                    break;      // 跳出内层循环 (列循环)
                }
            }
            if (!ok) { // 如果内层循环已确认排列无效
                break;  // 跳出外层循环 (行循环)
            }
        }

        if (ok) { // 如果当前排列通过了所有检查
            // 按顺序输出字符及其对应的数值
            for (int i = 0; i < k; ++i) {
                std::cout << C[i] << "=" << P[i] << (i == k - 1 ? "" : " ");
            }
            std::cout << std::endl;
            std::cout << base << std::endl; // 输出进制
            return 0; // 找到唯一解，程序结束
        }
    } while (std::next_permutation(P.begin(), P.end())); // 生成下一个值的排列

    // 如果所有排列都尝试完毕仍未找到解
    std::cout << "ERROR!" << std::endl;

    return 0;
}